-
Notifications
You must be signed in to change notification settings - Fork 501
Add CaseApply optimization
#7421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
c8d872c to
47a0318
Compare
47a0318 to
b8810a2
Compare
budget changesplutus-benchmark/bitwise/test/9.6/8
plutus-benchmark/bitwise/test/9.6/Ed25519.golden.eval
plutus-benchmark/cardano-loans/test/9.6/main.golden.eval
plutus-benchmark/coop/test/9.6/authMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/authMpMinting.golden.eval
plutus-benchmark/coop/test/9.6/certMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/certMpMinting.golden.eval
plutus-benchmark/coop/test/9.6/fsMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/fsMpMinting.golden.eval
plutus-benchmark/coop/test/9.6/mustBurnOwnSingleton.golden.eval
plutus-benchmark/linear-vesting/test/9.6/main.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-10.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-100.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-5.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-50.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-10.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-100.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-5.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-50.golden.eval
plutus-benchmark/lists/test/Sum/9.6/left-fold-built-in.golden.eval
plutus-benchmark/lists/test/Sum/9.6/left-fold-data.golden.eval
plutus-benchmark/lists/test/Sum/9.6/left-fold-scott.golden.eval
plutus-benchmark/lists/test/Sum/9.6/right-fold-built-in.golden.eval
plutus-benchmark/lists/test/Sum/9.6/right-fold-data.golden.eval
plutus-benchmark/lists/test/Sum/9.6/right-fold-scott.golden.eval
plutus-benchmark/nofib/test/9.6/clausify-F5.golden.eval
plutus-benchmark/nofib/test/9.6/knights10-4x4.golden.eval
plutus-benchmark/nofib/test/9.6/queens4-bt.golden.eval
plutus-benchmark/nofib/test/9.6/queens5-fc.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext1-20.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext1-4.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext2-20.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext2-4.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext1-20.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext1-4.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext2-20.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext2-4.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/sopFwdStakeTrick.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext1-20.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext1-4.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext2-20.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext2-4.golden.eval
plutus-benchmark/script-contexts/test/V3/Data/9.6/purposeIsWellFormed-4.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq1.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq2.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq3.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq4.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq5.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt1.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt2.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt3.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt4.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt5.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq1.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq2.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq3.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq4.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq5.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt1.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt2.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt3.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt4.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt5.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/mintValueBurned.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/mintValueMinted.golden.eval
plutus-tx-plugin/test/AsData/Budget/9.6/destructSum-manual.golden.eval
plutus-tx-plugin/test/AsData/Budget/9.6/destructSum.golden.eval
plutus-tx-plugin/test/AsData/Budget/9.6/recordFields.golden.eval
plutus-tx-plugin/test/Budget/9.6/constAccL.golden.eval
plutus-tx-plugin/test/Budget/9.6/constElL.golden.eval
plutus-tx-plugin/test/Budget/9.6/findIndexCheap.golden.eval
plutus-tx-plugin/test/Budget/9.6/findIndexEmptyList.golden.eval
plutus-tx-plugin/test/Budget/9.6/findIndexExpensive.golden.eval
plutus-tx-plugin/test/Budget/9.6/map1.golden.eval
plutus-tx-plugin/test/Budget/9.6/map2.golden.eval
plutus-tx-plugin/test/Budget/9.6/map3.golden.eval
plutus-tx-plugin/test/Budget/9.6/show.golden.eval
plutus-tx-plugin/test/Budget/9.6/sumL.golden.eval
plutus-tx-plugin/test/Budget/9.6/sumR.golden.eval
plutus-tx-plugin/test/BuiltinList/Budget/9.6/drop.golden.eval
plutus-tx-plugin/test/BuiltinList/Budget/9.6/take.golden.eval
plutus-tx-plugin/test/BuiltinList/Budget/9.6/uniqueElementJust.golden.eval
plutus-tx-plugin/test/CallTrace/9.6/successfullEvaluationYieldsNoTraceLog.golden.eval
|
plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Transform/CaseApply.hs
Outdated
Show resolved
Hide resolved
plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Transform/CaseApply.hs
Outdated
Show resolved
Hide resolved
|
I don't understand how this is an optimisation. Can you explain the logic behind it? |
|
You can check here: #7410 (comment) Basically, applying arguments using |
8d79313 to
253835b
Compare
plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Simplify.hs
Outdated
Show resolved
Hide resolved
plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Transform/CaseApply.hs
Show resolved
Hide resolved
plutus-core/untyped-plutus-core/src/UntypedPlutusCore/Transform/CaseApply.hs
Show resolved
Hide resolved
Execution Budget Golden Diffoutputplutus-benchmark/bitwise/test/9.6/8
plutus-benchmark/bitwise/test/9.6/Ed25519.golden.eval
plutus-benchmark/cardano-loans/test/9.6/main.golden.eval
plutus-benchmark/coop/test/9.6/authMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/authMpMinting.golden.eval
plutus-benchmark/coop/test/9.6/certMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/certMpMinting.golden.eval
plutus-benchmark/coop/test/9.6/fsMpBurning.golden.eval
plutus-benchmark/coop/test/9.6/fsMpMinting.golden.eval
plutus-benchmark/coop/test/9.6/mustBurnOwnSingleton.golden.eval
plutus-benchmark/linear-vesting/test/9.6/main.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-10.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-100.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-5.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-builtin-list-50.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-10.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-100.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-5.golden.eval
plutus-benchmark/lists/test/Lookup/9.6/match-scott-list-50.golden.eval
plutus-benchmark/lists/test/Sum/9.6/left-fold-built-in.golden.eval
plutus-benchmark/lists/test/Sum/9.6/left-fold-data.golden.eval
plutus-benchmark/lists/test/Sum/9.6/left-fold-scott.golden.eval
plutus-benchmark/lists/test/Sum/9.6/right-fold-built-in.golden.eval
plutus-benchmark/lists/test/Sum/9.6/right-fold-data.golden.eval
plutus-benchmark/lists/test/Sum/9.6/right-fold-scott.golden.eval
plutus-benchmark/nofib/test/9.6/clausify-F5.golden.eval
plutus-benchmark/nofib/test/9.6/knights10-4x4.golden.eval
plutus-benchmark/nofib/test/9.6/queens4-bt.golden.eval
plutus-benchmark/nofib/test/9.6/queens5-fc.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext1-20.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext1-4.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext2-20.golden.eval
plutus-benchmark/script-contexts/test/V1/9.6/checkScriptContext2-4.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext1-20.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext1-4.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext2-20.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/checkScriptContext2-4.golden.eval
plutus-benchmark/script-contexts/test/V2/9.6/sopFwdStakeTrick.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext1-20.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext1-4.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext2-20.golden.eval
plutus-benchmark/script-contexts/test/V3/9.6/checkScriptContext2-4.golden.eval
plutus-benchmark/script-contexts/test/V3/Data/9.6/purposeIsWellFormed-4.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq1.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq2.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq3.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq4.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/geq5.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt1.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt2.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt3.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt4.golden.eval
plutus-ledger-api/test-plugin/Spec/Budget/9.6/gt5.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq1.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq2.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq3.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq4.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/geq5.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt1.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt2.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt3.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt4.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/gt5.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/mintValueBurned.golden.eval
plutus-ledger-api/test-plugin/Spec/Data/Budget/9.6/mintValueMinted.golden.eval
plutus-tx-plugin/test/AsData/Budget/9.6/destructSum-manual.golden.eval
plutus-tx-plugin/test/AsData/Budget/9.6/destructSum.golden.eval
plutus-tx-plugin/test/AsData/Budget/9.6/recordFields.golden.eval
plutus-tx-plugin/test/Budget/9.6/constAccL.golden.eval
plutus-tx-plugin/test/Budget/9.6/constElL.golden.eval
plutus-tx-plugin/test/Budget/9.6/findIndexCheap.golden.eval
plutus-tx-plugin/test/Budget/9.6/findIndexEmptyList.golden.eval
plutus-tx-plugin/test/Budget/9.6/findIndexExpensive.golden.eval
plutus-tx-plugin/test/Budget/9.6/map1.golden.eval
plutus-tx-plugin/test/Budget/9.6/map2.golden.eval
plutus-tx-plugin/test/Budget/9.6/map3.golden.eval
plutus-tx-plugin/test/Budget/9.6/show.golden.eval
plutus-tx-plugin/test/Budget/9.6/sumL.golden.eval
plutus-tx-plugin/test/Budget/9.6/sumR.golden.eval
plutus-tx-plugin/test/BuiltinList/Budget/9.6/drop.golden.eval
plutus-tx-plugin/test/BuiltinList/Budget/9.6/take.golden.eval
plutus-tx-plugin/test/BuiltinList/Budget/9.6/uniqueElementJust.golden.eval
plutus-tx-plugin/test/CallTrace/9.6/successfullEvaluationYieldsNoTraceLog.golden.eval
This comment will get updated when changes are made. |
Are there any tests that display this behaviour? I'd actually expect that it would transform into (case (constr 0 (con integer 3) (con integer 2) (con integer 1)) (lam x (lam y (lam z. z)))) |
|
@basetunnel That's a good point. @SeungheonOh your notation is a bit confusing, Jacco is right that based on your notation, where application is parenthesized (in square brackets) to the right, the result wouldn't be correct. But looking at the implementation, it seems to be done fine. Remember, application is left-associative while lambda abstraction is right-associative. I've "mentally executed" the optimization on the following term, and I've applied the reduction semantics specified in the Plutus Core Spec. Looks good. However, I have some issues with the implementation. It's quite hard to read (so many recursive calls in so many places!!!), and it seems to traverse the term many many times so I would expect this optimization to be very computation heavy. If you look at how these optimization functions are called, it's not necessary for each optimization to recurse down the term itself. |
zliu41
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think that you should handle both [(\x . [(\y . t) b]) a] and [[(\x . (\y . t)) a] b], while you are at it. See Note [Multi-beta].
The implementation indeed seems more complex than needed like @ana-pantilie said. It shouldn't need to be much more different than the Beta pass.
| processNestedApp | ||
| :: Term name uni fun a | ||
| -> Term name uni fun a | ||
| processNestedApp (Apply ann body arg) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this not be implemented using transformOf termSubterms, which many other passes use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No: #7421 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe not seeing how Beta is done. I'll go over multi-beta note when I come back.
I didn't wanted to make this optimization on PIR at first but that might be the only way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't wanted to make this optimization on PIR at first but that might be the only way
I don't see why this needs to be done on PIR. I'm just suggesting that I expect the implementation to be similar to PIR's Beta pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SeungheonOh I think Ziyang is referring to beta = over termSubterms beta . localTransform, whereas transformOf l f = go where go = f . over l go, which instantiated to the beta case would be beta = localTransform . over termSubterms beta. So in the code for the beta optimization we're first applying the localTransform to the term, then we're recursing into its subterms. If you use transformOf, it first recurses into the subterms and then applies the localTransform.
I'm a bit annoyed by these lenses. I mean, they're nice, but I thought they would provide an interface similar to the one provided by recursion schemes. You know that you can implement basically any recursive list function in terms of foldr, and recursion schemes would allow you to generalize that to any tree-like structure. In particular, you can implement foldl in terms of foldr by replacing the "accumulating argument" with a function. Using recursion schemes, this generalizes to any type using the same technique! So you can implement both bottom-up and top-down algorithms using folds.
However, transformOf is very limited, and I wasn't able to figure out if the lens package provides a general fold such as cata. But it's possible I'm missing something quite simple, I never really fully understood lenses, although spending some time today to do so has been at least partially illuminating!
| -- Any nested application with fewer than 3 nested application is cheaper to represent | ||
| -- using a regular 'Apply' node. This is because the CaseApply optimization introduces | ||
| -- two AST nodes—'Constr' and 'Case'. Transforming a single application or a two-nested | ||
| -- application into 'Constr' and 'Case' actually hurts performance. | ||
| -- See #7410 for more information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
Adds "application through case/constr" optimization. Pretty decent free optimizations.
It is also possible to turn programs like
into
But this is only possible when the body of inner lambda doesn't reference variable bounded by all previous lambda abstractions. Maybe this is easier to do on PIR side.